/*
 * Copyright (c) 2021 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */
#include <stdio.h>
#include "hpm_mchtmr_drv.h"
#include "board.h"
#include "hpm_debug_console.h"
#include "hpm_pwm_drv.h"
#include "hpm_trgm_drv.h"
#include "hpm_trgmmux_src.h"
#include "hpm_gpio_drv.h"
#include "hpm_gptmr_drv.h"
#include "hpm_l1c_drv.h"
#include "hpm_adc16_drv.h"
#include "hpm_adc12_drv.h"
#include "multicore_common.h"
#include <string.h>

#define APP_BOARD_GPTMR_1               HPM_GPTMR1 
#define APP_BOARD_GPTMR_CH_1            0 
#define APP_BOARD_GPTMR_IRQ_1           IRQn_GPTMR1
#define APP_BOARD_GPTMR_CLOCK_1         clock_gptmr1
  
#define APP_BOARD_GPTMR_2               HPM_GPTMR2
#define APP_BOARD_GPTMR_CH_2            0
#define APP_BOARD_GPTMR_IRQ_2           IRQn_GPTMR2
#define APP_BOARD_GPTMR_CLOCK_2         clock_gptmr2

#define Nchirps (256)
#define Nchirps_Ignore (10) //采多几次，排除前几次的采样
#define Nsamples (256)

#define Frame_Period (200)   //ms
#define Chirp_Period_PING (100)   //us
#define Chirp_Period_PONG (100)   //us

#define Data_Total_Chirp                     (Nchirps_Ignore+Nchirps)

#define BOARD_ADC_DATA_BUFFER_LEN             (Nsamples)
#define BOARD_ADC_DMA_BUFFER_LEN              (BOARD_ADC_DATA_BUFFER_LEN+10+1)

#define BOARD_TRGM_SRC_PWM_CH                   HPM_TRGM0_INPUT_SRC_PWM0_CH8REF
#define BOARD_APP_ADC_TRIG_PWM                  HPM_PWM0
#define BOARD_APP_ADC_TRIG_TRGM                 HPM_TRGM0
#define BOARD_APP_CORE                          HPM_CORE0 

const uint16_t adc_dma_buffer_len = BOARD_ADC_DMA_BUFFER_LEN;

ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc0_seq_buff_PING[BOARD_ADC_DMA_BUFFER_LEN];
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc1_seq_buff_PING[BOARD_ADC_DMA_BUFFER_LEN];
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc2_seq_buff_PING[BOARD_ADC_DMA_BUFFER_LEN];
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc3_seq_buff_PING[BOARD_ADC_DMA_BUFFER_LEN];
                                      
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc0_seq_buff_PONG[BOARD_ADC_DMA_BUFFER_LEN];
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc1_seq_buff_PONG[BOARD_ADC_DMA_BUFFER_LEN];
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc2_seq_buff_PONG[BOARD_ADC_DMA_BUFFER_LEN];
ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(4) uint32_t adc3_seq_buff_PONG[BOARD_ADC_DMA_BUFFER_LEN];

int16_t one_dim_data[5][128*512] = {0};

uint8_t adc0_seq_channel[] = {7};
uint8_t adc1_seq_channel[] = {10};
uint8_t adc2_seq_channel[] = {11};
uint8_t adc3_seq_channel[] = {2};

extern void init_adc_pin_clock_trigger(void);
extern void init_common_config(adc12_conversion_mode_t conv_mode);
extern void init_sequence_config(ADC12_Type *ADC,uint32_t* data_addr,uint8_t channel_cfg_num,uint8_t* channel_list,uint8_t channel_num);
extern void init_ADC16_sequence_config(ADC16_Type *ADC,uint32_t* data_addr,uint8_t channel_cfg_num,uint8_t* channel_list,uint8_t channel_num);
extern void ADC_DMA_RESET(void* ADC_Base,uint32_t Addr);
extern void trigger_stop(PWM_Type * ptr);
extern void trigger_start(PWM_Type * ptr);

extern void timer_config_ms(GPTMR_Type * GPTMR,uint8_t ch_index,uint32_t priority,uint16_t ms);
extern void timer_config_us(GPTMR_Type * GPTMR,uint8_t ch_index,uint32_t priority,uint16_t us);
extern void timer_Rconfig_us(GPTMR_Type * GPTMR,uint8_t ch_index,uint32_t us);

void Store_Adc0_Data(void);
void Prepare_Adc_Sample(void);

typedef enum
{
  PING=0,
  PONG
}PP_ONG;

typedef enum
{
  FrameBegin=0,
  FrameEnd,
  ProcessPingData,
  ProcessPongData,
  DoNothing
}SampleRunTime;

volatile SampleRunTime RunTime = DoNothing;
volatile uint8_t Current_Frame;

volatile short Adc0_Current_Chirp_Num = 0;
volatile short Chirp_Num_A_Frame = 0;
volatile short Chirp_Num_B_Frame = 0;

volatile uint8_t FMCW_DATA_DONE = 0;
volatile uint16_t tmr2_cnt = 0;

void isr_adc0(void)
{
    trigger_stop(BOARD_APP_ADC_TRIG_PWM);
    volatile uint32_t adc0_int_sts = HPM_ADC0->INT_STS;
    if(adc0_int_sts & ADC12_INT_STS_SEQ_DMAABT_MASK)
    {
       adc12_clear_status_flags(HPM_ADC0, ADC12_INT_STS_SEQ_DMAABT_MASK); 
        if(Current_Frame == PONG)
        {
            ADC_DMA_RESET(HPM_ADC0,(uint32_t) &adc0_seq_buff_PING[0]);
            ADC_DMA_RESET(HPM_ADC1,(uint32_t) &adc1_seq_buff_PING[0]);
            ADC_DMA_RESET(HPM_ADC2,(uint32_t) &adc2_seq_buff_PING[0]);
            ADC_DMA_RESET(HPM_ADC3,(uint32_t) &adc3_seq_buff_PING[0]);
        }
        else
        {
            ADC_DMA_RESET(HPM_ADC0,(uint32_t) &adc0_seq_buff_PONG[0]);
            ADC_DMA_RESET(HPM_ADC1,(uint32_t) &adc1_seq_buff_PONG[0]);
            ADC_DMA_RESET(HPM_ADC2,(uint32_t) &adc2_seq_buff_PONG[0]);
            ADC_DMA_RESET(HPM_ADC3,(uint32_t) &adc3_seq_buff_PONG[0]);
        }
    } 
}
SDK_DECLARE_EXT_ISR_M(IRQn_ADC0, isr_adc0);

void tick_ms_isr(void)
{
    if (gptmr_check_status(APP_BOARD_GPTMR_1, GPTMR_CH_RLD_STAT_MASK(APP_BOARD_GPTMR_CH_1))) {
        gptmr_clear_status(APP_BOARD_GPTMR_1, GPTMR_CH_RLD_STAT_MASK(APP_BOARD_GPTMR_CH_1));
        RunTime = FrameBegin;
    }
}
SDK_DECLARE_EXT_ISR_M(APP_BOARD_GPTMR_IRQ_1, tick_ms_isr);

void tick_us_isr(void)
{
    if (gptmr_check_status(APP_BOARD_GPTMR_2, GPTMR_CH_RLD_STAT_MASK(APP_BOARD_GPTMR_CH_2))) {
        gptmr_clear_status(APP_BOARD_GPTMR_2, GPTMR_CH_RLD_STAT_MASK(APP_BOARD_GPTMR_CH_2));
        if(Current_Frame == PING)
        {
            Current_Frame = PONG;
            RunTime = ProcessPingData;
            timer_Rconfig_us(APP_BOARD_GPTMR_2,APP_BOARD_GPTMR_CH_2,Chirp_Period_PONG);
        }
        else
        {
            Current_Frame = PING;
            RunTime = ProcessPongData;
            timer_Rconfig_us(APP_BOARD_GPTMR_2,APP_BOARD_GPTMR_CH_2,Chirp_Period_PING);
        }
        tmr2_cnt++;
        if(tmr2_cnt==Data_Total_Chirp)
        {
            gptmr_disable_irq(APP_BOARD_GPTMR_2, GPTMR_CH_RLD_IRQ_MASK(APP_BOARD_GPTMR_CH_2));
            gptmr_stop_counter(APP_BOARD_GPTMR_2, APP_BOARD_GPTMR_CH_2);
            gptmr_channel_reset_count(APP_BOARD_GPTMR_2, APP_BOARD_GPTMR_CH_2);
        }else{
            trigger_start(BOARD_APP_ADC_TRIG_PWM);//触发adc采样
        }
    }
}
SDK_DECLARE_EXT_ISR_M(APP_BOARD_GPTMR_IRQ_2, tick_us_isr);

int main(void)
{
    board_init();
    
    init_adc_pin_clock_trigger();

    init_common_config(adc12_conv_mode_sequence);

    init_sequence_config(HPM_ADC0,(uint32_t*)adc0_seq_buff_PING,7,adc0_seq_channel,sizeof(adc0_seq_channel));
    init_sequence_config(HPM_ADC1,(uint32_t*)adc1_seq_buff_PING,10,adc1_seq_channel,sizeof(adc1_seq_channel));
    init_sequence_config(HPM_ADC2,(uint32_t*)adc2_seq_buff_PING,11,adc2_seq_channel,sizeof(adc2_seq_channel));
    init_ADC16_sequence_config(HPM_ADC3,(uint32_t*)adc3_seq_buff_PING,2,adc3_seq_channel,sizeof(adc3_seq_channel));

    Current_Frame = PING;

    #if BOARD_RUNNING_CORE == HPM_CORE0
        multicore_release_cpu(HPM_CORE1, SEC_CORE_IMG_START);
        board_delay_ms(50);//wait board 
    #endif
    timer_config_ms(APP_BOARD_GPTMR_1,APP_BOARD_GPTMR_CH_1,3,Frame_Period);//100ms   
    while(1)
    {
        switch(RunTime)
        {
            case FrameBegin:
              Prepare_Adc_Sample();
              RunTime = DoNothing;
              break;

            case ProcessPingData:
              Store_Adc0_Data();
              RunTime = DoNothing;
              break;

            case ProcessPongData:
              Store_Adc0_Data();
              RunTime = DoNothing;
              break;

            case DoNothing:
              break;
        }    
    }    
}

void Prepare_Adc_Sample(void)
{
    memset(one_dim_data,0x00,sizeof(one_dim_data));//在本行打断点
    Current_Frame = PING;
    tmr2_cnt = 0;//计算采样次数
    timer_config_us(APP_BOARD_GPTMR_2,APP_BOARD_GPTMR_CH_2,1,Chirp_Period_PING);
    trigger_start(BOARD_APP_ADC_TRIG_PWM);
    
    Chirp_Num_A_Frame = 0;
    Chirp_Num_B_Frame = 0;
}

void Store_Adc0_Data(void)
{
    uint16_t j=0;
    uint16_t j_PING =0;
    uint16_t j_PONG =0;


    if(Current_Frame == PONG)
    {  
        if(tmr2_cnt > Nchirps_Ignore){
            Chirp_Num_A_Frame ++;
        }
        for(short i = 10; i < 266; i++)
        { 
           one_dim_data[0][(Chirp_Num_A_Frame-1) * 512+j_PING] = ((adc0_seq_buff_PING[i]&0x0000fff0)>>4);
           one_dim_data[1][(Chirp_Num_A_Frame-1) * 512+j_PING] = ((adc1_seq_buff_PING[i]&0x0000fff0)>>4);
           one_dim_data[2][(Chirp_Num_A_Frame-1) * 512+j_PING] = ((adc2_seq_buff_PING[i]&0x0000fff0)>>4);
           one_dim_data[3][(Chirp_Num_A_Frame-1) * 512+j_PING] = ((adc3_seq_buff_PING[i]&0x0000fff0)>>4);
           j_PING ++;
        }
        
    }
    else
    {
        if(tmr2_cnt > Nchirps_Ignore){
            Chirp_Num_B_Frame ++;
        }
        for(short i = 10; i < 266; i++)
        {
            one_dim_data[4][(Chirp_Num_B_Frame-1) * 512+j_PONG] = ((adc0_seq_buff_PONG[i]&0x0000fff0)>>4);
            j_PONG ++;
        }  
                 
    }
    
}

//static uint64_t time = 0;
//static double total_time_1= 0.0f;
//time = mchtmr_get_count(HPM_MCHTMR);
//time = mchtmr_get_count(HPM_MCHTMR) - time;
//if(Chirp_Num_A_Frame == 10)
//{
//    printf("time = %lld\r\n",time);
//    total_time_1 = time*(1000000.0f/24000000);
//    printf("delta_time_1 = %.1fus\n", total_time_1);
//    while(1){}
//} 